#pragma once

#include<iostream>
#include<unordered_map>
#include<memory>
#include "Epoller.hpp"
#include "Log.hpp"
#include "Connection.hpp"

using namespace LogModule;

class Reactor
{
    static const int revs_num = 128;
private:
    bool IsConnectionEmpty()
    {
        return _connections.empty();
    }
    
    void PrintConnection()
    {
        std::cout << "当前Reactor管理的fd list:";
        for(auto& con:_connections)
        {
            std::cout << con.second->GetSockfd() << " ";
        }
        std::cout<<std::endl;
    }

    void Dispatcher(int n)//事件派发器
    {
        for(int i = 0;i<n;i++)
        {
            int sockfd = _revs[i].data.fd;
            uint32_t revents = _revs[i].events;
            //将所有异常处理统一转换为IO异常，统一调用一个IO异常处理函数
            if(revents & EPOLLERR)
                revents |= (EPOLLIN | EPOLLOUT);
            if(revents & EPOLLHUP)
                revents |= (EPOLLIN | EPOLLOUT);
            
            //读事件就绪
            if(revents & EPOLLIN)
            {
                _connections[sockfd]->Recver();
            }
            if(revents & EPOLLOUT)
            {
                _connections[sockfd]->Sender();
            }
        }
    }

public:
    Reactor()
    :_epoller_ptr(std::make_unique<Epoller>())
    ,_isrunning(false)
    {}

    ~Reactor(){}

    void Start()
    {
        if(IsConnectionEmpty())
            return;
        
        _isrunning = true;
        int timeout = -1;
        while(_isrunning)
        {
            PrintConnection();//DEBUG
            int n = _epoller_ptr->WaitEvents(_revs,revs_num,timeout);
            Dispatcher(n);
        }
        _isrunning = false;
    }

    void Stop()
    {
        _isrunning = false;
    }

    void AddConnection(std::shared_ptr<Connection>& conn)
    {
        //不能重复添加 TODO
        
        //1.conn对应的fd和其关心的事件写透到内核中
        int sockfd = conn->GetSockfd();
        uint32_t events = conn->GetEvents();
        _epoller_ptr->AddEvent(sockfd,events);

        //2.设置该conn的回指指针
        conn->SetOwner(this);

        //3.将该conn添加到_connections中
        _connections[sockfd] = conn;
    }

    void EnableReadOrWrite(int sockfd,bool enableread,bool enablewrite)
    {
        //1.建立新的关系事件new_events
        uint32_t new_events = (EPOLLET | (enableread?EPOLLIN:0) | (enablewrite?EPOLLOUT:0));
        
        //2.更新其对应的connection
        _connections[sockfd]->SetEvents(new_events); 

        //3.写透到内核中
        _epoller_ptr->ModEvent(sockfd,new_events);
    }

    void DelConnection(int sockfd)
    {
        //1.从内核移除
        _epoller_ptr->DelEvent(sockfd);

        //2.从_connections移除
        _connections.erase(sockfd);

        //3.关闭sockfd
        close(sockfd);
        LOG(LogLevel::INFO) << "client quit:" << sockfd;
    }

private:
    std::unique_ptr<Epoller> _epoller_ptr;//epoll模型
    bool _isrunning;//是否启动

    //管理所有connection  fd:connection
    std::unordered_map<int,std::shared_ptr<Connection>> _connections;
    //就绪队列
    struct epoll_event _revs[revs_num];
};
